package com.hulk.boot.dubbo.autoconfigure;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.I0Itec.zkclient.ZkClient;
import org.jboss.netty.bootstrap.Bootstrap;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.actuate.health.CompositeHealthIndicator;
import org.springframework.boot.actuate.health.HealthAggregator;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.boot.actuate.metrics.export.Exporter;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ConsumerConfig;
import com.alibaba.dubbo.config.ModuleConfig;
import com.alibaba.dubbo.config.MonitorConfig;
import com.alibaba.dubbo.config.ProtocolConfig;
import com.alibaba.dubbo.config.ProviderConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.spring.AnnotationBean;
import com.alibaba.dubbo.config.spring.ReferenceBean;
import com.alibaba.dubbo.config.spring.ServiceBean;
import com.hulk.boot.dubbo.endpoint.DubboEndpoint;
import com.hulk.boot.dubbo.health.DubboHealthIndicator;

@Configuration
@ConditionalOnClass({Exporter.class, ReferenceBean.class, ServiceBean.class,AnnotationBean.class,Bootstrap.class,ZkClient.class })
@EnableConfigurationProperties(DubboProperties.class)
public class DubboAutoConfiguration {

    @Autowired
    private DubboProperties dubboProperties;

    @Bean
    @ConditionalOnMissingBean
    public ApplicationConfig requestApplicationConfig() {
        return dubboProperties.getApplication();
    }


    @Bean
    @ConditionalOnMissingBean
    public RegistryConfig requestRegistryConfig() {
        return dubboProperties.getRegistry();
    }


    @Bean
    public ProtocolConfig requestProtocolConfig() {
    	List<ProtocolConfig> l = dubboProperties.getProtocol();
    	if(l==null || l.isEmpty()){
    		return new 	ProtocolConfig();
    	}
    	if(l.get(0) == null){
    		return new 	ProtocolConfig();
    	}
        return l.get(0);
    }

    @Bean
    public ProtocolConfig requestProtocolConfig1() {
    	List<ProtocolConfig> l = dubboProperties.getProtocol();
    	if(l==null || l.isEmpty()|| 1>=l.size()){
    		return new 	ProtocolConfig();
    	}
    	
        return l.get(1);
    }
    
    @Bean
    public ProtocolConfig requestProtocolConfig2() {
    	List<ProtocolConfig> l = dubboProperties.getProtocol();
    	if(l==null || l.isEmpty()|| 2>=l.size()){
    		return new 	ProtocolConfig();
    	}
    	
        return l.get(2);
    }
    
    @Bean
    public ProtocolConfig requestProtocolConfig3() {
    	List<ProtocolConfig> l = dubboProperties.getProtocol();
    	if(l==null || l.isEmpty()|| 3>=l.size()){
    		return new 	ProtocolConfig();
    	}
    	
        return l.get(3);
    }
    
    @Bean
    public ProtocolConfig requestProtocolConfig4() {
    	List<ProtocolConfig> l = dubboProperties.getProtocol();
    	if(l==null || l.isEmpty()|| 4>=l.size()){
    		return new 	ProtocolConfig();
    	}
    	
        return l.get(4);
    }
    
    @Bean
    @ConfigurationProperties(prefix = "endpoints.dubbo", ignoreUnknownFields = false)
    public DubboEndpoint dubboEndpoint() {
        return new DubboEndpoint();
    }

    @Bean
    @ConditionalOnMissingBean
    public ConsumerConfig requestConsumerConfig(){
        return dubboProperties.getConsumerConfig();
    }

    @Bean
    @ConditionalOnMissingBean
    public ProviderConfig requestProviderConfig(){
        return dubboProperties.getProviderConfig();
    }

    @Bean
    @ConditionalOnMissingBean
    public MonitorConfig monitorConfig(){
        return dubboProperties.getMonitorConfig();
    }

    @Bean
    @ConditionalOnMissingBean
    public ModuleConfig moduleConfig(){
        return dubboProperties.getModuleConfig();
    }


  /*  @Bean
    public DubboHealthIndicator dubboHealthIndicator() {
        return new DubboHealthIndicator();
    }*/


	@Autowired
	HealthAggregator healthAggregator;
	
	@Autowired(required=false)
	Map<String,ReferenceBean> references;
	
	@Bean
	
	public HealthIndicator dubboHealthIndicator(){
		if (references == null){
			return null;
		}
		Map<String,HealthIndicator> indicators = new HashMap<>();
		for (String key :references.keySet()){
			final ReferenceBean bean =references.get(key);
			indicators.put(key.startsWith("&")?key.replaceFirst("&", ""): key, new DubboHealthIndicator(bean));
		}
		return new CompositeHealthIndicator(healthAggregator,indicators);
		
	}
    

}
